Find out how the risktaking was set together and how they are measured

Each preference measure is standardized at the individual level, so that, by construction, each preference has a mean of zero and a standard deviation of one in the individual-level world sample.

Find out about the overlap

Concept: What do we want

Next steps: - what visualization do we want to do (why)? - always age and gender in the plots - Intercept age, intercept for age, intercept gender, intercept n

#Load packages

library(data.table)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
data.table 1.14.8 using 1 threads (see ?getDTthreads).  Latest news: r-datatable.com
**********
This installation of data.table has not detected OpenMP support. It should still work but in single-threaded mode.
This is a Mac. Please read https://mac.r-project.org/openmp/. Please engage with Apple and ask them for support. Check r-datatable.com for updates, and our Mac instructions here: https://github.com/Rdatatable/data.table/wiki/Installation. After several years of many reports of installation problems on Mac, it's time to gingerly point out that there have been no similar problems on Windows or Linux.
**********
library(tidyr)
library(haven)
library(ggplot2)
library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:data.table’:

    between, first, last

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(gridExtra)

Attaching package: ‘gridExtra’

The following object is masked from ‘package:dplyr’:

    combine
library(lmtest)
Loading required package: zoo

Attaching package: ‘zoo’

The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric

#Add data GPS

# Einlesen des Datensets
gps_data <- haven::read_dta("/Users/laurabazzigher/Documents/GitHub/risk_wvs/data/dataset/GPS_dataset_individual_level/individual_new.dta")

# Anzeige der ersten Zeilen des Datensets
head(country_data)

Number of courtries

# Determine the number of different countries
number_of_countries <- length(unique(gps_data$country))

# Display the number of different countries
number_of_countries
[1] 76

Clean the data from missing values

# Clean the data by removing records with missing values
cleaned_data <- gps_data %>%
  drop_na(country, isocode, risktaking, gender, age)

# Calculate the number of records removed per variable
records_removed_per_variable <- colSums(is.na(gps_data)) - colSums(is.na(cleaned_data))

# Display the cleaned data
cleaned_data

# Display the number of records removed per variable
records_removed_per_variable
         country          isocode             ison           region         language             date 
               0                0                0                0                0                0 
       id_gallup              wgt         patience       risktaking         posrecip         negrecip 
               0                0              190              634               32              247 
        altruism            trust subj_math_skills           gender              age 
              74              163              132                0              276 

List of all variable

# List all variables
variable_list <- names(cleaned_data) # OR colnames(your_data)

# Display the list of variables
print(variable_list)
 [1] "country"          "isocode"          "ison"             "region"           "language"        
 [6] "date"             "id_gallup"        "wgt"              "patience"         "risktaking"      
[11] "posrecip"         "negrecip"         "altruism"         "trust"            "subj_math_skills"
[16] "gender"           "age"             

#select only the variables of interest

cleaned_data <- cleaned_data %>%
  select(country, isocode, ison, date, risktaking, gender, age)
cleaned_data

Boxplot of some variables

# Liste der zu löschenden Variablen
to_be_deleted_variables <- c(region, language, id_gallup, wgt, patience, posrecip, negrecip, altruism, trust, subj_math_skills)
Error: object 'region' not found

All about the age

# Age Range
age_min <- min(cleaned_data$age, na.rm = TRUE)
age_max <- max(cleaned_data$age, na.rm = TRUE)

# Average Age
average_age <- mean(cleaned_data$age, na.rm = TRUE)

# Median Age
median_age <- median(cleaned_data$age, na.rm = TRUE)
Error in `median()`:
! `median.haven_labelled()` not implemented.
Backtrace:
 1. stats::median(cleaned_data$age, na.rm = TRUE)
 2. vctrs:::median.vctrs_vctr(cleaned_data$age, na.rm = TRUE)

All about the gender

# Calculate the counts of females (gender = 1) and males (gender = 2)
gender_counts <- table(cleaned_data$gender)

# Display the counts
cat("Number of Females: ", gender_counts[1], "\n")
Number of Females:  36024 
cat("Number of Males: ", gender_counts[2], "\n")
Number of Males:  43415 

Table with country and gender

# Create a table that breaks down the number of participants by country and gender
gender_by_country <- xtabs(~ country + gender, data = cleaned_data)

# Rename columns and rows for better readability
colnames(gender_by_country) <- c("Female", "Male")
rownames(gender_by_country) <- unique(cleaned_data$country)

# Calculate the total participants by summing the rows
total_participants <- rowSums(gender_by_country)



# Create a data frame with country, total participants, female, and male
result_table <- data.frame(
  country = rownames(gender_by_country),
  total_participants = total_participants,
  female = gender_by_country[, "Female"],
  male = gender_by_country[, "Male"]
)

# Display the result table
result_table

# Create a table with the following information: country, isocode, n (count of participants), female percentage (%), mean age, age range, and risktaking
####### add intercept and slope (age, gender, parental status, occupational status, education)
# Intercept und Slope für Alter
intercept_age <- coef(model)["(Intercept)"]
slope_age <- coef(model)["age"]

# Intercept und Slope für Geschlecht
intercept_gender <- coef(model)["(Intercept)"]
slope_gender <- coef(model)["gender"]

summary(model)

Call:
lm(formula = risktaking ~ age, data = cleaned_data)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.24386 -0.68385 -0.04386  0.65311  3.05477 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.5759701  0.0089312   64.49   <2e-16 ***
age         -0.0137902  0.0001974  -69.84   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.9707 on 79437 degrees of freedom
Multiple R-squared:  0.05786,   Adjusted R-squared:  0.05784 
F-statistic:  4878 on 1 and 79437 DF,  p-value: < 2.2e-16

Create a table with the following information: country, isocode, n (count of participants), female percentage (%), mean age, age range, and risktaking

add intercept and slope (age, gender, parental status, occupational status, education)

# Group the data by country
table_data <- gps_data %>%
  group_by(country, isocode) %>%
  summarize(
    n = n(),
    female_percentage = mean(gender == 1) * 100,
    mean_age = mean(age, na.rm = TRUE),
    age_range = paste(min(age, na.rm = TRUE), "-", max(age, na.rm = TRUE)),
    mean_risktaking = mean(risktaking, na.rm = TRUE)
  )
`summarise()` has grouped output by 'country'. You can override using the `.groups` argument.
# Intercept and slope for age
intercept_age <- 0.5  # Replace with your actual intercept
slope_age <- 0.2      # Replace with your actual slope

# Intercept and slope for gender
intercept_gender <- -0.3  # Replace with your actual intercept
slope_gender <- 0.1       # Replace with your actual slope

# Intercept and slope for parental status
intercept_parental <- 0.1  # Replace with your actual intercept
slope_parental <- 0.05     # Replace with your actual slope

# Intercept and slope for occupational status
intercept_occupation <- 0.2  # Replace with your actual intercept
slope_occupation <- 0.03    # Replace with your actual slope

# Intercept and slope for education
intercept_education <- 0.4  # Replace with your actual intercept
slope_education <- 0.08     # Replace with your actual slope

# Add the intercept and slope information to the table
table_data <- table_data %>%
  mutate(
    intercept_age = intercept_age,
    slope_age = slope_age,
    intercept_gender = intercept_gender,
    slope_gender = slope_gender,
    intercept_parental = intercept_parental,
    slope_parental = slope_parental,
    intercept_occupation = intercept_occupation,
    slope_occupation = slope_occupation,
    intercept_education = intercept_education,
    slope_education = slope_education
  )

# Display the updated table
table_data
NA

Create a new column “age_group” with the age categories

cleaned_data$agecat <- cut(
  cleaned_data$age,
  breaks = c(15, 20, 30, 40, 50, 60, 70, 80, Inf), # The category boundaries
  labels = c("15-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80+"), # The category labels
  right = FALSE # Left end (inclusive), right end (exclusive)
)

# Display the new column
head(cleaned_data)

Number of participants in each age category

# number of participants in each age category
agecat_counts <- table(cleaned_data$agecat)

# Display the number of participants in the age categories
print(agecat_counts)

15-19 20-29 30-39 40-49 50-59 60-69 70-79   80+ 
 6888 16872 15905 13583 11374  8570  4688  1559 

Perform a correlation analysis on variables patience, risktaking, altruism and trust

# Calculate the correlation matrix with NA removal
correlation_matrix <- cor(cleaned_data[, c("patience", "risktaking", "altruism", "trust")], use = "pairwise.complete.obs")

# Print the correlation matrix
print(correlation_matrix)
             patience risktaking   altruism      trust
patience   1.00000000 0.20573586 0.08397351 0.06404146
risktaking 0.20573586 1.00000000 0.09524941 0.03517175
altruism   0.08397351 0.09524941 1.00000000 0.16734183
trust      0.06404146 0.03517175 0.16734183 1.00000000

checking the assumptions in a linear regression

# Scatterplot to check for linearity
ggplot(cleaned_data, aes(x = age, y = risktaking)) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE, color = "blue") +
  labs(title = "Scatterplot for Linearity Check")

# Residual vs. Fitted plot to check for homoskedasticity
model <- lm(risktaking ~ age, data = cleaned_data)
ggplot() +
  geom_point(aes(x = fitted(model), y = residuals(model))) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(title = "Residuals vs. Fitted Values for Homoskedasticity Check")

# Q-Q plot to check for normality of residuals
qqnorm(residuals(model))
qqline(residuals(model))

# Correlation matrix to check for multicollinearity
cor(cleaned_data[c("age", "risktaking")])
                  age risktaking
age         1.0000000 -0.2405333
risktaking -0.2405333  1.0000000
# Durbin-Watson test for autocorrelation
dwtest(model)

    Durbin-Watson test

data:  model
DW = 1.5415, p-value < 2.2e-16
alternative hypothesis: true autocorrelation is greater than 0
# Residual vs. Leverage plot to check for outliers
ggplot() +
  geom_point(aes(x = hatvalues(model), y = residuals(model))) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(title = "Residuals vs. Leverage for Outlier Check")

#Preparing for linear regression

# Check for missing values in 'Country' and 'Risktaking' columns
missing_country <- anyNA(cleaned_data$country)
missing_risktaking <- anyNA(cleaned_data$risktaking)

# Print the results
cat("Missing values in 'Country': ", missing_country, "\n")
Missing values in 'Country':  FALSE 
cat("Missing values in 'Risktaking': ", missing_risktaking, "\n")
Missing values in 'Risktaking':  FALSE 
# Clean the data by removing records with missing values
cleaned_data <- gps_data %>%
  drop_na(country, risktaking, age)

# Split the data by country and perform linear regression for each country
regression_results <- cleaned_data %>%
  group_by(country) %>%
  do(model = lm(risktaking ~ age, data = .)) %>%
  summarize(
    country = first(country),
    intercept = summary(model)$coefficients[1],
    slope = summary(model)$coefficients[2],
    r_squared = summary(model)$r.squared
  )

# Display regression results for each country
print(regression_results)

analyze the results by using “Balkendiagramm

what does 0 mean? // centered age = mean age of the sample
ggplot(data = regression_results, aes(x = country, y = intercept)) +
  geom_bar(stat = "identity", fill = "blue") +
  labs(title = "Intercepts for Risktaking by Country", x = "Country", y = "Intercept Value") +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

View the countries with intercept values over 0.75

high_intercept_countries <- subset(regression_results, intercept > 0.75)

# View the countries with intercept values over 0.75
print(high_intercept_countries)

Scatterplots for ‘high_intercept_countries’ contains the top 17 countries

# Create scatterplots with regression lines for countries with intercept > 0.75 and smaller points
plots <- lapply(1:nrow(regression_results), function(i) {
  country <- regression_results$country[i]
  intercept <- regression_results$intercept[i]
  
  if (intercept > 0.75) {
    p <- ggplot(subset(cleaned_data, country == country), aes(x = age, y = risktaking)) +
      geom_point(size = 0.5) +  # Set the size to a smaller value (e.g., 2)
      geom_smooth(method = "lm", formula = y ~ x, se = FALSE, color = "blue") +
      labs(title = paste("Linear Regression for", country),
           subtitle = paste("Intercept:", round(intercept, 2)))
    print(p)
  }
})


# Save the plots in a directory
dir.create("individual_country_plots", showWarnings = FALSE)
setwd("individual_country_plots")
Warning: The working directory was changed to /Users/laurabazzigher/Documents/GitHub/risk_wvs/code/individual_country_plots inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
for (i in seq_along(plots)) {
  filename <- paste0("plot_", i, ".png")
  ggsave(filename, plot = plots[[i]], width = 8, height = 6)
}


# Switch back to the original working directory
setwd("..")

print("Individual plots for countries with intercept > 0.75 and smaller points are saved in the 'individual_country_plots' directory.")
[1] "Individual plots for countries with intercept > 0.75 and smaller points are saved in the 'individual_country_plots' directory."

Create scatterplots with regression lines for individual countries

regression_results <- data.frame(
  country = c("Algeria", "Argentina", "Austria"),
  intercept = c(0.92053422, 0.51698822, 0.42606684),
  slope = c(-0.0146641801, -0.0115569623, -0.0108763042),
  r_squared = c(5.232529e-02, 5.638271e-02, 3.539810e-02    )
)

# Create scatterplots with regression lines for each country
plots <- lapply(seq_len(nrow(regression_results)), function(i) {
  country <- regression_results$country[i]
  intercept <- regression_results$intercept[i]
  slope <- regression_results$slope[i]
  r_squared <- regression_results$r_squared[i]
  
  p <- ggplot(subset(cleaned_data, country == country), aes(x = age, y = risktaking)) +
    geom_point() +
    geom_smooth(method = "lm", formula = y ~ x, se = FALSE, color = "blue") +
    labs(title = paste("Linear Regression for", country),
         subtitle = paste("Intercept:", round(intercept, 2),
                           "Slope:", round(slope, 2),
                           "R-squared:", round(r_squared, 2)))
  print(p)
})


# Save the plots in a directory
dir.create("individual_country_plots", showWarnings = FALSE)
setwd("individual_country_plots")
Warning: The working directory was changed to /Users/laurabazzigher/Documents/GitHub/risk_wvs/code/individual_country_plots inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
for (i in seq_along(plots)) {
  filename <- paste0("plot_", i, ".png")
  ggsave(filename, plot = plots[[i]], width = 8, height = 6)
}


# Switch back to the original working directory
setwd("..")

print("Individual plots are saved in the 'individual_country_plots' directory.")
[1] "Individual plots are saved in the 'individual_country_plots' directory."

Create a scatterplot with separate regression lines for each country

# Calculate the overall regression line
overall_lm <- lm(risktaking ~ age, data = cleaned_data) # Regression over all countries

ggplot(cleaned_data, aes(x = age, y = risktaking, color = country)) +
  geom_point(size = 0.2) +                           # Adjust point size
  geom_smooth(method = "lm", se = FALSE, size = 0.5, linetype = "solid") + # Adjust line size and type
  labs(title = "Scatterplot with Regression Lines for risktaking and age by Country", 
       x = "Age", y = "Risktaking") +
  theme(legend.position = "bottom",              # Move the legend below the graph
        legend.key.size = unit(0.1, "in"))      # Adjust the size of the legend key

Scatterplot with include both individual country regression lines and an overall regression line

# Calculate the overall regression line
overall_lm <- lm(risktaking ~ age, data = cleaned_data)

# Create a scatterplot with separate regression lines for each country
# and an overall regression line
ggplot(cleaned_data, aes(x = age, y = risktaking, color = country)) +
  geom_point(size = 0.5) +                      # Adjust point size
  geom_smooth(method = "lm", se = FALSE, size = 0.5) + # Solid line for individual countries
  geom_abline(intercept = coef(overall_lm)[1], slope = coef(overall_lm)[2], 
              color = "red", size = 1) + # Add the overall regression line in red
  labs(title = "Scatterplot with Regression Lines for risktaking and age by Country", 
       x = "Age", y = "Risktaking") +
  theme(legend.position = "bottom",          # Move the legend below the graph
        legend.key.size = unit(0.1, "in"))  # Adjust the size of the legend key

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBGaW5kIG91dCBob3cgdGhlIHJpc2t0YWtpbmcgd2FzIHNldCB0b2dldGhlciBhbmQgaG93IHRoZXkgYXJlIG1lYXN1cmVkCkVhY2ggcHJlZmVyZW5jZSBtZWFzdXJlIGlzIHN0YW5kYXJkaXplZCBhdCB0aGUgaW5kaXZpZHVhbCBsZXZlbCwgc28gdGhhdCwgYnkgY29uc3RydWN0aW9uLCBlYWNoIHByZWZlcmVuY2UgaGFzIGEgbWVhbiBvZiB6ZXJvIGFuZCBhIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBvbmUgaW4gdGhlIGluZGl2aWR1YWwtbGV2ZWwgd29ybGQgc2FtcGxlLgoKIyBGaW5kIG91dCBhYm91dCB0aGUgb3ZlcmxhcAotIHNhbWUgY291bnRyaWVzIAotIGZhY2lkIHdyYXAgLS0+IFBsb3QgYnkgY291bnRyeQotIHNjYXR0ZXJwbG90cyAtLT4gbWVhbiBjb3VudHJ5IC8vIG1lYW4gcmlzayAKCiMgQ29uY2VwdDogV2hhdCBkbyB3ZSB3YW50IAotIFJpc2t0YWtpbmcgYW5kIGFnZSBzbG9wZQotIFBsb3QgaXQgYnkgaG93IHN0ZWVwIHRoZSBzbG9wZSBpcwotLT4gUnVuIGl0IGluIGFuIG1peGVkIGVmZmVjdCBtb2RlbCAoc2VlIHBhcGVyIGZyb20gUnVpKQoKIyMjIyMjIyMjIyMKTmV4dCBzdGVwczogCi0gd2hhdCB2aXN1YWxpemF0aW9uIGRvIHdlIHdhbnQgdG8gZG8gKHdoeSk/IAotIGFsd2F5cyBhZ2UgYW5kIGdlbmRlciBpbiB0aGUgcGxvdHMKLSBJbnRlcmNlcHQgYWdlLCBpbnRlcmNlcHQgZm9yIGFnZSwgaW50ZXJjZXB0IGdlbmRlciwgaW50ZXJjZXB0IG4KCiNMb2FkIHBhY2thZ2VzIApgYGB7cn0KbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGhhdmVuKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGxtdGVzdCkKYGBgCgojQWRkIGRhdGEgR1BTCmBgYHtyfQpncHNfZGF0YSA8LSBoYXZlbjo6cmVhZF9kdGEoIi9Vc2Vycy9sYXVyYWJhenppZ2hlci9Eb2N1bWVudHMvR2l0SHViL3Jpc2tfd3ZzL2RhdGEvZGF0YXNldC9HUFNfZGF0YXNldF9pbmRpdmlkdWFsX2xldmVsL2luZGl2aWR1YWxfbmV3LmR0YSIpCgpoZWFkKGNvdW50cnlfZGF0YSkKYGBgCiMgTnVtYmVyIG9mIGNvdXJ0cmllcyAKYGBge3J9CiMgRGV0ZXJtaW5lIHRoZSBudW1iZXIgb2YgZGlmZmVyZW50IGNvdW50cmllcwpudW1iZXJfb2ZfY291bnRyaWVzIDwtIGxlbmd0aCh1bmlxdWUoZ3BzX2RhdGEkY291bnRyeSkpCgojIERpc3BsYXkgdGhlIG51bWJlciBvZiBkaWZmZXJlbnQgY291bnRyaWVzCm51bWJlcl9vZl9jb3VudHJpZXMKYGBgCgojIENsZWFuIHRoZSBkYXRhIGZyb20gbWlzc2luZyB2YWx1ZXMKYGBge3J9CiMgQ2xlYW4gdGhlIGRhdGEgYnkgcmVtb3ZpbmcgcmVjb3JkcyB3aXRoIG1pc3NpbmcgdmFsdWVzCmNsZWFuZWRfZGF0YSA8LSBncHNfZGF0YSAlPiUKICBkcm9wX25hKGNvdW50cnksIGlzb2NvZGUsIHJpc2t0YWtpbmcsIGdlbmRlciwgYWdlKQoKIyBDYWxjdWxhdGUgdGhlIG51bWJlciBvZiByZWNvcmRzIHJlbW92ZWQgcGVyIHZhcmlhYmxlCnJlY29yZHNfcmVtb3ZlZF9wZXJfdmFyaWFibGUgPC0gY29sU3Vtcyhpcy5uYShncHNfZGF0YSkpIC0gY29sU3Vtcyhpcy5uYShjbGVhbmVkX2RhdGEpKQoKIyBEaXNwbGF5IHRoZSBjbGVhbmVkIGRhdGEKY2xlYW5lZF9kYXRhCgojIERpc3BsYXkgdGhlIG51bWJlciBvZiByZWNvcmRzIHJlbW92ZWQgcGVyIHZhcmlhYmxlCnJlY29yZHNfcmVtb3ZlZF9wZXJfdmFyaWFibGUKYGBgCgojIExpc3Qgb2YgYWxsIHZhcmlhYmxlCmBgYHtyfQojIExpc3QgYWxsIHZhcmlhYmxlcwp2YXJpYWJsZV9saXN0IDwtIG5hbWVzKGNsZWFuZWRfZGF0YSkgIyBPUiBjb2xuYW1lcyh5b3VyX2RhdGEpCgojIERpc3BsYXkgdGhlIGxpc3Qgb2YgdmFyaWFibGVzCnByaW50KHZhcmlhYmxlX2xpc3QpCmBgYAojc2VsZWN0IG9ubHkgdGhlIHZhcmlhYmxlcyBvZiBpbnRlcmVzdApgYGB7cn0KY2xlYW5lZF9kYXRhIDwtIGNsZWFuZWRfZGF0YSAlPiUKICBzZWxlY3QoY291bnRyeSwgaXNvY29kZSwgaXNvbiwgZGF0ZSwgcmlza3Rha2luZywgZ2VuZGVyLCBhZ2UpCmNsZWFuZWRfZGF0YQpgYGAKCgojIEJveHBsb3Qgb2Ygc29tZSB2YXJpYWJsZXMKYGBge3J9CmJveHBsb3QoY2xlYW5lZF9kYXRhJGFnZSwgbWFpbiA9ICJCb3hwbG90IG9mIEFnZSIpCmJveHBsb3QoY2xlYW5lZF9kYXRhJHBhdGllbmNlLCBtYWluID0gIkJveHBsb3Qgb2YgUGF0aWVuY2UiKQpib3hwbG90KGNsZWFuZWRfZGF0YSRyaXNrdGFraW5nLCBtYWluID0gIkJveHBsb3Qgb2YgUmlza3Rha2luZyIpCmBgYAojIEFsbCBhYm91dCB0aGUgYWdlCmBgYHtyfQojIEFnZSBSYW5nZQphZ2VfbWluIDwtIG1pbihjbGVhbmVkX2RhdGEkYWdlLCBuYS5ybSA9IFRSVUUpCmFnZV9tYXggPC0gbWF4KGNsZWFuZWRfZGF0YSRhZ2UsIG5hLnJtID0gVFJVRSkKCiMgQXZlcmFnZSBBZ2UKYXZlcmFnZV9hZ2UgPC0gbWVhbihjbGVhbmVkX2RhdGEkYWdlLCBuYS5ybSA9IFRSVUUpCgojIE1lZGlhbiBBZ2UKbWVkaWFuX2FnZSA8LSBtZWRpYW4oY2xlYW5lZF9kYXRhJGFnZSwgbmEucm0gPSBUUlVFKQoKIyBEaXNwbGF5IHRoZSBhZ2Ugc3RhdGlzdGljcwpjYXQoIkFnZSBSYW5nZTogIiwgYWdlX21pbiwgIiB0byAiLCBhZ2VfbWF4LCAiXG4iKQpjYXQoIkF2ZXJhZ2UgQWdlOiAiLCBhdmVyYWdlX2FnZSwgIlxuIikKY2F0KCJNZWRpYW4gQWdlOiAiLCBtZWRpYW5fYWdlLCAiXG4iKQpgYGAKCiMgQWxsIGFib3V0IHRoZSBnZW5kZXIKYGBge3J9CiMgQ2FsY3VsYXRlIHRoZSBjb3VudHMgb2YgZmVtYWxlcyAoZ2VuZGVyID0gMSkgYW5kIG1hbGVzIChnZW5kZXIgPSAyKQpnZW5kZXJfY291bnRzIDwtIHRhYmxlKGNsZWFuZWRfZGF0YSRnZW5kZXIpCgojIERpc3BsYXkgdGhlIGNvdW50cwpjYXQoIk51bWJlciBvZiBGZW1hbGVzOiAiLCBnZW5kZXJfY291bnRzWzFdLCAiXG4iKQpjYXQoIk51bWJlciBvZiBNYWxlczogIiwgZ2VuZGVyX2NvdW50c1syXSwgIlxuIikKYGBgCgojIFRhYmxlIHdpdGggY291bnRyeSBhbmQgZ2VuZGVyCmBgYHtyfQojIENyZWF0ZSBhIHRhYmxlIHRoYXQgYnJlYWtzIGRvd24gdGhlIG51bWJlciBvZiBwYXJ0aWNpcGFudHMgYnkgY291bnRyeSBhbmQgZ2VuZGVyCmdlbmRlcl9ieV9jb3VudHJ5IDwtIHh0YWJzKH4gY291bnRyeSArIGdlbmRlciwgZGF0YSA9IGNsZWFuZWRfZGF0YSkKCiMgUmVuYW1lIGNvbHVtbnMgYW5kIHJvd3MgZm9yIGJldHRlciByZWFkYWJpbGl0eQpjb2xuYW1lcyhnZW5kZXJfYnlfY291bnRyeSkgPC0gYygiRmVtYWxlIiwgIk1hbGUiKQpyb3duYW1lcyhnZW5kZXJfYnlfY291bnRyeSkgPC0gdW5pcXVlKGNsZWFuZWRfZGF0YSRjb3VudHJ5KQoKIyBDYWxjdWxhdGUgdGhlIHRvdGFsIHBhcnRpY2lwYW50cyBieSBzdW1taW5nIHRoZSByb3dzCnRvdGFsX3BhcnRpY2lwYW50cyA8LSByb3dTdW1zKGdlbmRlcl9ieV9jb3VudHJ5KQoKIyBDcmVhdGUgYSBkYXRhIGZyYW1lIHdpdGggY291bnRyeSwgdG90YWwgcGFydGljaXBhbnRzLCBmZW1hbGUsIGFuZCBtYWxlCnJlc3VsdF90YWJsZSA8LSBkYXRhLmZyYW1lKAogIGNvdW50cnkgPSByb3duYW1lcyhnZW5kZXJfYnlfY291bnRyeSksCiAgdG90YWxfcGFydGljaXBhbnRzID0gdG90YWxfcGFydGljaXBhbnRzLAogIGZlbWFsZSA9IGdlbmRlcl9ieV9jb3VudHJ5WywgIkZlbWFsZSJdLAogIG1hbGUgPSBnZW5kZXJfYnlfY291bnRyeVssICJNYWxlIl0KKQoKIyBEaXNwbGF5IHRoZSByZXN1bHQgdGFibGUKcmVzdWx0X3RhYmxlCmBgYAoKYGBge3J9CiMgSW50ZXJjZXB0IHVuZCBTbG9wZSBmw7xyIEFsdGVyCmludGVyY2VwdF9hZ2UgPC0gY29lZihtb2RlbClbIihJbnRlcmNlcHQpIl0Kc2xvcGVfYWdlIDwtIGNvZWYobW9kZWwpWyJhZ2UiXQoKIyBJbnRlcmNlcHQgdW5kIFNsb3BlIGbDvHIgR2VzY2hsZWNodAppbnRlcmNlcHRfZ2VuZGVyIDwtIGNvZWYobW9kZWwpWyIoSW50ZXJjZXB0KSJdCnNsb3BlX2dlbmRlciA8LSBjb2VmKG1vZGVsKVsiZ2VuZGVyIl0KCnN1bW1hcnkobW9kZWwpCmBgYAoKIyBDcmVhdGUgYSB0YWJsZSB3aXRoIHRoZSBmb2xsb3dpbmcgaW5mb3JtYXRpb246IGNvdW50cnksIGlzb2NvZGUsIG4gKGNvdW50IG9mIHBhcnRpY2lwYW50cyksIGZlbWFsZSBwZXJjZW50YWdlICglKSwgbWVhbiBhZ2UsIGFnZSByYW5nZSwgYW5kIHJpc2t0YWtpbmcKIyMjIyMjIyBhZGQgaW50ZXJjZXB0IGFuZCBzbG9wZSAoYWdlLCBnZW5kZXIsIHBhcmVudGFsIHN0YXR1cywgb2NjdXBhdGlvbmFsIHN0YXR1cywgZWR1Y2F0aW9uKQpgYGB7cn0KIyBHcm91cCB0aGUgZGF0YSBieSBjb3VudHJ5CnRhYmxlX2RhdGEgPC0gZ3BzX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY291bnRyeSwgaXNvY29kZSkgJT4lCiAgc3VtbWFyaXplKAogICAgbiA9IG4oKSwKICAgIGZlbWFsZV9wZXJjZW50YWdlID0gbWVhbihnZW5kZXIgPT0gMSkgKiAxMDAsCiAgICBtZWFuX2FnZSA9IG1lYW4oYWdlLCBuYS5ybSA9IFRSVUUpLAogICAgYWdlX3JhbmdlID0gcGFzdGUobWluKGFnZSwgbmEucm0gPSBUUlVFKSwgIi0iLCBtYXgoYWdlLCBuYS5ybSA9IFRSVUUpKSwKICAgIG1lYW5fcmlza3Rha2luZyA9IG1lYW4ocmlza3Rha2luZywgbmEucm0gPSBUUlVFKQogICkKCgojIEludGVyY2VwdCBhbmQgc2xvcGUgZm9yIGFnZQppbnRlcmNlcHRfYWdlIDwtIDAuNSAgIyBSZXBsYWNlIHdpdGggeW91ciBhY3R1YWwgaW50ZXJjZXB0CnNsb3BlX2FnZSA8LSAwLjIgICAgICAjIFJlcGxhY2Ugd2l0aCB5b3VyIGFjdHVhbCBzbG9wZQoKIyBJbnRlcmNlcHQgYW5kIHNsb3BlIGZvciBnZW5kZXIKaW50ZXJjZXB0X2dlbmRlciA8LSAtMC4zICAjIFJlcGxhY2Ugd2l0aCB5b3VyIGFjdHVhbCBpbnRlcmNlcHQKc2xvcGVfZ2VuZGVyIDwtIDAuMSAgICAgICAjIFJlcGxhY2Ugd2l0aCB5b3VyIGFjdHVhbCBzbG9wZQoKIyBBZGQgdGhlIGludGVyY2VwdCBhbmQgc2xvcGUgaW5mb3JtYXRpb24gdG8gdGhlIHRhYmxlCnRhYmxlX2RhdGEgPC0gdGFibGVfZGF0YSAlPiUKICBtdXRhdGUoCiAgICBpbnRlcmNlcHRfYWdlID0gaW50ZXJjZXB0X2FnZSwKICAgIHNsb3BlX2FnZSA9IHNsb3BlX2FnZSwKICAgIGludGVyY2VwdF9nZW5kZXIgPSBpbnRlcmNlcHRfZ2VuZGVyLAogICAgc2xvcGVfZ2VuZGVyID0gc2xvcGVfZ2VuZGVyLAogICAgaW50ZXJjZXB0X3BhcmVudGFsID0gaW50ZXJjZXB0X3BhcmVudGFsLAogICAgc2xvcGVfcGFyZW50YWwgPSBzbG9wZV9wYXJlbnRhbCwKICAgIGludGVyY2VwdF9vY2N1cGF0aW9uID0gaW50ZXJjZXB0X29jY3VwYXRpb24sCiAgICBzbG9wZV9vY2N1cGF0aW9uID0gc2xvcGVfb2NjdXBhdGlvbiwKICAgIGludGVyY2VwdF9lZHVjYXRpb24gPSBpbnRlcmNlcHRfZWR1Y2F0aW9uLAogICAgc2xvcGVfZWR1Y2F0aW9uID0gc2xvcGVfZWR1Y2F0aW9uCiAgKQoKIyBEaXNwbGF5IHRoZSB1cGRhdGVkIHRhYmxlCnRhYmxlX2RhdGEKCmBgYAoKIyBDcmVhdGUgYSBuZXcgY29sdW1uICJhZ2VfZ3JvdXAiIHdpdGggdGhlIGFnZSBjYXRlZ29yaWVzCmBgYHtyfQpjbGVhbmVkX2RhdGEkYWdlY2F0IDwtIGN1dCgKICBjbGVhbmVkX2RhdGEkYWdlLAogIGJyZWFrcyA9IGMoMTUsIDIwLCAzMCwgNDAsIDUwLCA2MCwgNzAsIDgwLCBJbmYpLCAjIFRoZSBjYXRlZ29yeSBib3VuZGFyaWVzCiAgbGFiZWxzID0gYygiMTUtMTkiLCAiMjAtMjkiLCAiMzAtMzkiLCAiNDAtNDkiLCAiNTAtNTkiLCAiNjAtNjkiLCAiNzAtNzkiLCAiODArIiksICMgVGhlIGNhdGVnb3J5IGxhYmVscwogIHJpZ2h0ID0gRkFMU0UgIyBMZWZ0IGVuZCAoaW5jbHVzaXZlKSwgcmlnaHQgZW5kIChleGNsdXNpdmUpCikKCiMgRGlzcGxheSB0aGUgbmV3IGNvbHVtbgpoZWFkKGNsZWFuZWRfZGF0YSkKYGBgCgojIE51bWJlciBvZiBwYXJ0aWNpcGFudHMgaW4gZWFjaCBhZ2UgY2F0ZWdvcnkKYGBge3J9CiMgbnVtYmVyIG9mIHBhcnRpY2lwYW50cyBpbiBlYWNoIGFnZSBjYXRlZ29yeQphZ2VjYXRfY291bnRzIDwtIHRhYmxlKGNsZWFuZWRfZGF0YSRhZ2VjYXQpCgojIERpc3BsYXkgdGhlIG51bWJlciBvZiBwYXJ0aWNpcGFudHMgaW4gdGhlIGFnZSBjYXRlZ29yaWVzCnByaW50KGFnZWNhdF9jb3VudHMpCmBgYAoKCiMgUGVyZm9ybSBhIGNvcnJlbGF0aW9uIGFuYWx5c2lzIG9uIHZhcmlhYmxlcyBwYXRpZW5jZSwgcmlza3Rha2luZywgYWx0cnVpc20gYW5kIHRydXN0CmBgYHtyfQojIENhbGN1bGF0ZSB0aGUgY29ycmVsYXRpb24gbWF0cml4IHdpdGggTkEgcmVtb3ZhbApjb3JyZWxhdGlvbl9tYXRyaXggPC0gY29yKGNsZWFuZWRfZGF0YVssIGMoInBhdGllbmNlIiwgInJpc2t0YWtpbmciLCAiYWx0cnVpc20iLCAidHJ1c3QiKV0sIHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQoKIyBQcmludCB0aGUgY29ycmVsYXRpb24gbWF0cml4CnByaW50KGNvcnJlbGF0aW9uX21hdHJpeCkKCmBgYAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgY2hlY2tpbmcgdGhlIGFzc3VtcHRpb25zIGluIGEgbGluZWFyIHJlZ3Jlc3Npb24gIApgYGB7cn0KIyBTY2F0dGVycGxvdCB0byBjaGVjayBmb3IgbGluZWFyaXR5CmdncGxvdChjbGVhbmVkX2RhdGEsIGFlcyh4ID0gYWdlLCB5ID0gcmlza3Rha2luZykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gImJsdWUiKSArCiAgbGFicyh0aXRsZSA9ICJTY2F0dGVycGxvdCBmb3IgTGluZWFyaXR5IENoZWNrIikKYGBgCmBgYHtyfQojIFJlc2lkdWFsIHZzLiBGaXR0ZWQgcGxvdCB0byBjaGVjayBmb3IgaG9tb3NrZWRhc3RpY2l0eQptb2RlbCA8LSBsbShyaXNrdGFraW5nIH4gYWdlLCBkYXRhID0gY2xlYW5lZF9kYXRhKQpnZ3Bsb3QoKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGZpdHRlZChtb2RlbCksIHkgPSByZXNpZHVhbHMobW9kZWwpKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gInJlZCIpICsKICBsYWJzKHRpdGxlID0gIlJlc2lkdWFscyB2cy4gRml0dGVkIFZhbHVlcyBmb3IgSG9tb3NrZWRhc3RpY2l0eSBDaGVjayIpCmBgYAoKYGBge3J9CiMgUS1RIHBsb3QgdG8gY2hlY2sgZm9yIG5vcm1hbGl0eSBvZiByZXNpZHVhbHMKcXFub3JtKHJlc2lkdWFscyhtb2RlbCkpCnFxbGluZShyZXNpZHVhbHMobW9kZWwpKQpgYGAKCmBgYHtyfQojIENvcnJlbGF0aW9uIG1hdHJpeCB0byBjaGVjayBmb3IgbXVsdGljb2xsaW5lYXJpdHkKY29yKGNsZWFuZWRfZGF0YVtjKCJhZ2UiLCAicmlza3Rha2luZyIpXSkKYGBgCgpgYGB7cn0KIyBEdXJiaW4tV2F0c29uIHRlc3QgZm9yIGF1dG9jb3JyZWxhdGlvbgpkd3Rlc3QobW9kZWwpCmBgYAoKYGBge3J9CiMgUmVzaWR1YWwgdnMuIExldmVyYWdlIHBsb3QgdG8gY2hlY2sgZm9yIG91dGxpZXJzCmdncGxvdCgpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gaGF0dmFsdWVzKG1vZGVsKSwgeSA9IHJlc2lkdWFscyhtb2RlbCkpKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAicmVkIikgKwogIGxhYnModGl0bGUgPSAiUmVzaWR1YWxzIHZzLiBMZXZlcmFnZSBmb3IgT3V0bGllciBDaGVjayIpCmBgYAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgoKCiNQcmVwYXJpbmcgZm9yIGxpbmVhciByZWdyZXNzaW9uCmBgYHtyfQojIENoZWNrIGZvciBtaXNzaW5nIHZhbHVlcyBpbiAnQ291bnRyeScgYW5kICdSaXNrdGFraW5nJyBjb2x1bW5zCm1pc3NpbmdfY291bnRyeSA8LSBhbnlOQShjbGVhbmVkX2RhdGEkY291bnRyeSkKbWlzc2luZ19yaXNrdGFraW5nIDwtIGFueU5BKGNsZWFuZWRfZGF0YSRyaXNrdGFraW5nKQoKIyBQcmludCB0aGUgcmVzdWx0cwpjYXQoIk1pc3NpbmcgdmFsdWVzIGluICdDb3VudHJ5JzogIiwgbWlzc2luZ19jb3VudHJ5LCAiXG4iKQpjYXQoIk1pc3NpbmcgdmFsdWVzIGluICdSaXNrdGFraW5nJzogIiwgbWlzc2luZ19yaXNrdGFraW5nLCAiXG4iKQoKYGBgCgoKYGBge3J9CiMgQ2xlYW4gdGhlIGRhdGEgYnkgcmVtb3ZpbmcgcmVjb3JkcyB3aXRoIG1pc3NpbmcgdmFsdWVzCmNsZWFuZWRfZGF0YSA8LSBncHNfZGF0YSAlPiUKICBkcm9wX25hKGNvdW50cnksIHJpc2t0YWtpbmcsIGFnZSkKCiMgU3BsaXQgdGhlIGRhdGEgYnkgY291bnRyeSBhbmQgcGVyZm9ybSBsaW5lYXIgcmVncmVzc2lvbiBmb3IgZWFjaCBjb3VudHJ5CnJlZ3Jlc3Npb25fcmVzdWx0cyA8LSBjbGVhbmVkX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY291bnRyeSkgJT4lCiAgZG8obW9kZWwgPSBsbShyaXNrdGFraW5nIH4gYWdlLCBkYXRhID0gLikpICU+JQogIHN1bW1hcml6ZSgKICAgIGNvdW50cnkgPSBmaXJzdChjb3VudHJ5KSwKICAgIGludGVyY2VwdCA9IHN1bW1hcnkobW9kZWwpJGNvZWZmaWNpZW50c1sxXSwKICAgIHNsb3BlID0gc3VtbWFyeShtb2RlbCkkY29lZmZpY2llbnRzWzJdLAogICAgcl9zcXVhcmVkID0gc3VtbWFyeShtb2RlbCkkci5zcXVhcmVkCiAgKQoKIyBEaXNwbGF5IHJlZ3Jlc3Npb24gcmVzdWx0cyBmb3IgZWFjaCBjb3VudHJ5CnByaW50KHJlZ3Jlc3Npb25fcmVzdWx0cykKYGBgCgoKIyBhbmFseXplIHRoZSByZXN1bHRzIGJ5IHVzaW5nICJCYWxrZW5kaWFncmFtbQojIyMjIyMgd2hhdCBkb2VzIDAgbWVhbj8gLy8gY2VudGVyZWQgYWdlID0gbWVhbiBhZ2Ugb2YgdGhlIHNhbXBsZQpgYGB7cn0KZ2dwbG90KGRhdGEgPSByZWdyZXNzaW9uX3Jlc3VsdHMsIGFlcyh4ID0gY291bnRyeSwgeSA9IGludGVyY2VwdCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJibHVlIikgKwogIGxhYnModGl0bGUgPSAiSW50ZXJjZXB0cyBmb3IgUmlza3Rha2luZyBieSBDb3VudHJ5IiwgeCA9ICJDb3VudHJ5IiwgeSA9ICJJbnRlcmNlcHQgVmFsdWUiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkKYGBgCiMgVmlldyB0aGUgY291bnRyaWVzIHdpdGggaW50ZXJjZXB0IHZhbHVlcyBvdmVyIDAuNzUKYGBge3J9CmhpZ2hfaW50ZXJjZXB0X2NvdW50cmllcyA8LSBzdWJzZXQocmVncmVzc2lvbl9yZXN1bHRzLCBpbnRlcmNlcHQgPiAwLjc1KQoKIyBWaWV3IHRoZSBjb3VudHJpZXMgd2l0aCBpbnRlcmNlcHQgdmFsdWVzIG92ZXIgMC43NQpwcmludChoaWdoX2ludGVyY2VwdF9jb3VudHJpZXMpCmBgYAoKCiMgU2NhdHRlcnBsb3RzIGZvciAnaGlnaF9pbnRlcmNlcHRfY291bnRyaWVzJyBjb250YWlucyB0aGUgdG9wIDE3IGNvdW50cmllcwpgYGB7cn0KIyBDcmVhdGUgc2NhdHRlcnBsb3RzIHdpdGggcmVncmVzc2lvbiBsaW5lcyBmb3IgY291bnRyaWVzIHdpdGggaW50ZXJjZXB0ID4gMC43NSBhbmQgc21hbGxlciBwb2ludHMKcGxvdHMgPC0gbGFwcGx5KDE6bnJvdyhyZWdyZXNzaW9uX3Jlc3VsdHMpLCBmdW5jdGlvbihpKSB7CiAgY291bnRyeSA8LSByZWdyZXNzaW9uX3Jlc3VsdHMkY291bnRyeVtpXQogIGludGVyY2VwdCA8LSByZWdyZXNzaW9uX3Jlc3VsdHMkaW50ZXJjZXB0W2ldCiAgCiAgaWYgKGludGVyY2VwdCA+IDAuNzUpIHsKICAgIHAgPC0gZ2dwbG90KHN1YnNldChjbGVhbmVkX2RhdGEsIGNvdW50cnkgPT0gY291bnRyeSksIGFlcyh4ID0gYWdlLCB5ID0gcmlza3Rha2luZykpICsKICAgICAgZ2VvbV9wb2ludChzaXplID0gMC41KSArICAjIFNldCB0aGUgc2l6ZSB0byBhIHNtYWxsZXIgdmFsdWUgKGUuZy4sIDIpCiAgICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSB5IH4geCwgc2UgPSBGQUxTRSwgY29sb3IgPSAiYmx1ZSIpICsKICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJMaW5lYXIgUmVncmVzc2lvbiBmb3IiLCBjb3VudHJ5KSwKICAgICAgICAgICBzdWJ0aXRsZSA9IHBhc3RlKCJJbnRlcmNlcHQ6Iiwgcm91bmQoaW50ZXJjZXB0LCAyKSkpCiAgICBwcmludChwKQogIH0KfSkKCiMgU2F2ZSB0aGUgcGxvdHMgaW4gYSBkaXJlY3RvcnkKZGlyLmNyZWF0ZSgiaW5kaXZpZHVhbF9jb3VudHJ5X3Bsb3RzIiwgc2hvd1dhcm5pbmdzID0gRkFMU0UpCnNldHdkKCJpbmRpdmlkdWFsX2NvdW50cnlfcGxvdHMiKQoKZm9yIChpIGluIHNlcV9hbG9uZyhwbG90cykpIHsKICBmaWxlbmFtZSA8LSBwYXN0ZTAoInBsb3RfIiwgaSwgIi5wbmciKQogIGdnc2F2ZShmaWxlbmFtZSwgcGxvdCA9IHBsb3RzW1tpXV0sIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKfQoKIyBTd2l0Y2ggYmFjayB0byB0aGUgb3JpZ2luYWwgd29ya2luZyBkaXJlY3RvcnkKc2V0d2QoIi4uIikKCnByaW50KCJJbmRpdmlkdWFsIHBsb3RzIGZvciBjb3VudHJpZXMgd2l0aCBpbnRlcmNlcHQgPiAwLjc1IGFuZCBzbWFsbGVyIHBvaW50cyBhcmUgc2F2ZWQgaW4gdGhlICdpbmRpdmlkdWFsX2NvdW50cnlfcGxvdHMnIGRpcmVjdG9yeS4iKQpgYGAKCiMgQ3JlYXRlIHNjYXR0ZXJwbG90cyB3aXRoIHJlZ3Jlc3Npb24gbGluZXMgZm9yIGluZGl2aWR1YWwgY291bnRyaWVzCmBgYHtyfQojIEV4YW1wbGVzIGZvciBjb3VudHJpZXMKcmVncmVzc2lvbl9yZXN1bHRzIDwtIGRhdGEuZnJhbWUoCiAgY291bnRyeSA9IGMoIkFsZ2VyaWEiLCAiQXJnZW50aW5hIiwgIkF1c3RyaWEiKSwKICBpbnRlcmNlcHQgPSBjKDAuOTIwNTM0MjIsIDAuNTE2OTg4MjIsIDAuNDI2MDY2ODQpLAogIHNsb3BlID0gYygtMC4wMTQ2NjQxODAxLCAtMC4wMTE1NTY5NjIzLCAtMC4wMTA4NzYzMDQyKSwKICByX3NxdWFyZWQgPSBjKDUuMjMyNTI5ZS0wMiwgNS42MzgyNzFlLTAyLCAzLjUzOTgxMGUtMDIJKQopCgojIENyZWF0ZSBzY2F0dGVycGxvdHMgd2l0aCByZWdyZXNzaW9uIGxpbmVzIGZvciBlYWNoIGNvdW50cnkKcGxvdHMgPC0gbGFwcGx5KHNlcV9sZW4obnJvdyhyZWdyZXNzaW9uX3Jlc3VsdHMpKSwgZnVuY3Rpb24oaSkgewogIGNvdW50cnkgPC0gcmVncmVzc2lvbl9yZXN1bHRzJGNvdW50cnlbaV0KICBpbnRlcmNlcHQgPC0gcmVncmVzc2lvbl9yZXN1bHRzJGludGVyY2VwdFtpXQogIHNsb3BlIDwtIHJlZ3Jlc3Npb25fcmVzdWx0cyRzbG9wZVtpXQogIHJfc3F1YXJlZCA8LSByZWdyZXNzaW9uX3Jlc3VsdHMkcl9zcXVhcmVkW2ldCiAgCiAgcCA8LSBnZ3Bsb3Qoc3Vic2V0KGNsZWFuZWRfZGF0YSwgY291bnRyeSA9PSBjb3VudHJ5KSwgYWVzKHggPSBhZ2UsIHkgPSByaXNrdGFraW5nKSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSB5IH4geCwgc2UgPSBGQUxTRSwgY29sb3IgPSAiYmx1ZSIpICsKICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiTGluZWFyIFJlZ3Jlc3Npb24gZm9yIiwgY291bnRyeSksCiAgICAgICAgIHN1YnRpdGxlID0gcGFzdGUoIkludGVyY2VwdDoiLCByb3VuZChpbnRlcmNlcHQsIDIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiU2xvcGU6Iiwgcm91bmQoc2xvcGUsIDIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiUi1zcXVhcmVkOiIsIHJvdW5kKHJfc3F1YXJlZCwgMikpKQogIHByaW50KHApCn0pCgojIFNhdmUgdGhlIHBsb3RzIGluIGEgZGlyZWN0b3J5CmRpci5jcmVhdGUoImluZGl2aWR1YWxfY291bnRyeV9wbG90cyIsIHNob3dXYXJuaW5ncyA9IEZBTFNFKQpzZXR3ZCgiaW5kaXZpZHVhbF9jb3VudHJ5X3Bsb3RzIikKCmZvciAoaSBpbiBzZXFfYWxvbmcocGxvdHMpKSB7CiAgZmlsZW5hbWUgPC0gcGFzdGUwKCJwbG90XyIsIGksICIucG5nIikKICBnZ3NhdmUoZmlsZW5hbWUsIHBsb3QgPSBwbG90c1tbaV1dLCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCn0KCiMgU3dpdGNoIGJhY2sgdG8gdGhlIG9yaWdpbmFsIHdvcmtpbmcgZGlyZWN0b3J5CnNldHdkKCIuLiIpCgpwcmludCgiSW5kaXZpZHVhbCBwbG90cyBhcmUgc2F2ZWQgaW4gdGhlICdpbmRpdmlkdWFsX2NvdW50cnlfcGxvdHMnIGRpcmVjdG9yeS4iKQpgYGAKCiMgQ3JlYXRlIGEgc2NhdHRlcnBsb3Qgd2l0aCBzZXBhcmF0ZSByZWdyZXNzaW9uIGxpbmVzIGZvciBlYWNoIGNvdW50cnkKYGBge3J9CmdncGxvdChjbGVhbmVkX2RhdGEsIGFlcyh4ID0gYWdlLCB5ID0gcmlza3Rha2luZywgY29sb3IgPSBjb3VudHJ5KSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMikgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICMgQWRqdXN0IHBvaW50IHNpemUKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBzaXplID0gMC41LCBsaW5ldHlwZSA9ICJzb2xpZCIpICsgIyBBZGp1c3QgbGluZSBzaXplIGFuZCB0eXBlCiAgbGFicyh0aXRsZSA9ICJTY2F0dGVycGxvdCB3aXRoIFJlZ3Jlc3Npb24gTGluZXMgZm9yIHJpc2t0YWtpbmcgYW5kIGFnZSBieSBDb3VudHJ5IiwgCiAgICAgICB4ID0gIkFnZSIsIHkgPSAiUmlza3Rha2luZyIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgICAgICAgICAgICAgICMgTW92ZSB0aGUgbGVnZW5kIGJlbG93IHRoZSBncmFwaAogICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC4xLCAiaW4iKSkgICAgICAjIEFkanVzdCB0aGUgc2l6ZSBvZiB0aGUgbGVnZW5kIGtleQpgYGAKCiMgU2NhdHRlcnBsb3Qgd2l0aCBpbmNsdWRlIGJvdGggaW5kaXZpZHVhbCBjb3VudHJ5IHJlZ3Jlc3Npb24gbGluZXMgYW5kIGFuIG92ZXJhbGwgcmVncmVzc2lvbiBsaW5lCmBgYHtyfQojIENhbGN1bGF0ZSB0aGUgb3ZlcmFsbCByZWdyZXNzaW9uIGxpbmUKb3ZlcmFsbF9sbSA8LSBsbShyaXNrdGFraW5nIH4gYWdlLCBkYXRhID0gY2xlYW5lZF9kYXRhKQoKIyBDcmVhdGUgYSBzY2F0dGVycGxvdCB3aXRoIHNlcGFyYXRlIHJlZ3Jlc3Npb24gbGluZXMgZm9yIGVhY2ggY291bnRyeQojIGFuZCBhbiBvdmVyYWxsIHJlZ3Jlc3Npb24gbGluZQpnZ3Bsb3QoY2xlYW5lZF9kYXRhLCBhZXMoeCA9IGFnZSwgeSA9IHJpc2t0YWtpbmcsIGNvbG9yID0gY291bnRyeSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjUpICsgICAgICAgICAgICAgICAgICAgICAgIyBBZGp1c3QgcG9pbnQgc2l6ZQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIHNpemUgPSAwLjUpICsgIyBTb2xpZCBsaW5lIGZvciBpbmRpdmlkdWFsIGNvdW50cmllcwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IGNvZWYob3ZlcmFsbF9sbSlbMV0sIHNsb3BlID0gY29lZihvdmVyYWxsX2xtKVsyXSwgCiAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDEpICsgIyBBZGQgdGhlIG92ZXJhbGwgcmVncmVzc2lvbiBsaW5lIGluIHJlZAogIGxhYnModGl0bGUgPSAiU2NhdHRlcnBsb3Qgd2l0aCBSZWdyZXNzaW9uIExpbmVzIGZvciByaXNrdGFraW5nIGFuZCBhZ2UgYnkgQ291bnRyeSIsIAogICAgICAgeCA9ICJBZ2UiLCB5ID0gIlJpc2t0YWtpbmciKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsICAgICAgICAgICMgTW92ZSB0aGUgbGVnZW5kIGJlbG93IHRoZSBncmFwaAogICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC4xLCAiaW4iKSkgICMgQWRqdXN0IHRoZSBzaXplIG9mIHRoZSBsZWdlbmQga2V5CmBgYAoKCg==